[Chapter 33] 33.8 Alphabetized Reference
Author: Bryan Costales & Eric Allman
Date: 1999-01-06T20:26:11Z

#

| Chapter 33 Database Macros |

## 33.8 Alphabetized Reference

Recall that the `K` configuration command (see Section 33.3) is used like this:

>     Kname class args

The `class` determines the type of database that will be used. For example, the class `btree` causes the Berkeley db(3) to be used, whereas the class `dequote` causes an internal routine of sendmail's to be called.

In this section we present all the classes in alphabetical order. They are summarized in Table 33.3 of Section 33.3.2. Most interaction with these classes can be watched by using the `-d38.2` debugging switch (see Section 37.5.128). Some specialty maps use other debugging switches, which we indicate where appropriate.

### 33.8.1 btree

Berkeley's db form of database

(V8.1 and above)

> The term btree stands for "balanced tree." It is a grow-only form of database. Lookups and insertions are fast, but deletions do not shrink the database. A good description of this form of database can be found in The Art of Computer Programming, Vol. 3: Sorting and Searching, D.E. Knuth, 1968, pp. 471-480. The btree class is available only if sendmail was compiled with `NEWDB` defined and the new Berkeley db library linked in.

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with this class and the meaning of each.

### 33.8.2 bestmx

Look up the best MX record for a host

(V8.7 and above)

> The `bestmx` map class looks up a hostname as the `key` and returns the current best MX record as the `value`. Internally, a call is made to getmxrr() to get a list of MX records for the host. That list is sorted in order of the best to the worst, and `bestmx` returns the first. Because bestmx is a class, not a map, you need to declare it with a `K` configuration command before you can use it:

> >     Kbestmx bestmx

> One use for this class might be to see whether a particular host has a usable MX at all:

> >     Kbestmx bestmx
> >     ...
> >     R$*< @ $+ > $*                $: $1<@$2>$3 <$(bestmx $2 $: NO $)>
> >     R$*< @ $+ > $* < NO >         $#smtp  $@ $2 $: $1 < @ $2 > $3
> >     R$*< @ $+ > $* < $* >         $: $1<@ $[ $2 $] > $3

> In the first rule we look up the host part of an address (which has already been focused by rule set 3) with the `bestmx` database map. The result of the lookup is surrounded with angle brackets and appended to the original address. The second rule looks for the `NO` caused by an unsuccessful lookup (the `$:`). The original address is then sent with the `smtp` delivery agent. If the hostname inside the appended angle braces is not `NO`, the host part of the original address is canonicalized with the `$[` and `$]` operators.

> This `bestmx` class is a special internal one that can take advantage of only two of the `K` command switches: the `-a` (as you saw) and the `-q` (to suppress dequoting the key). This class can be watched with the `-d8` debugging switch (see Section 37.5.30, -d8.1).

### 33.8.3 dbm

Really ndbm supplied with most versions of UNIX

(V8.1 and above)

> The dbm class, which is really the ndbm form of database, is the traditional form of UNIX database. Data are stored in one file, keys in another. The data must fit in blocks of fixed sizes, so there is usually a limit on the maximum size (1 kilobyte or so) on any given stored datum. The dbm class is available only if sendmail was compiled with `NDBM` declared (see Section 18.8.24, NDBM).

> This is the class of database traditionally used with alias files. Because of the limit on the size of a datum, you should consider using one of the db(3) `hash` or `btree` classes instead.

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with the class and the meaning of each switch.

### 33.8.4 dequote

A pseudo map for removing quotation marks

(V8.6 and above)

> V8 sendmail can remove quotation marks from around tokens by using the special dequote class. Because dequote is a class, not a map, you need to declare it with a `K` configuration command before you can use it:

> >     Kunquote dequote

> This declares a map named `unquote` of the class `dequote`. Once a map name has been declared, the `dequote` class can be used in the RHS of rules to remove quotation marks. It is used with `$(` and `$)`, just like database lookups:

> >     $(unquote tokens $)

> Here, arbitrary `tokens` are looked up in the database named `unquote`. That database is special because it is of the class `dequote`. Instead of really being looked up in a database, `tokens` will just have any surrounding quotation marks removed:

> >     "A.B.C"           becomes   A.B.C
> >     "A"."B"."C"       becomes   A.B.C
> >     "A B"             becomes   "A B"
> >     "A,B"             becomes   "A,B"
> >     "A>B"             becomes   "A>B"

> The first example shows that surrounding quotation marks are removed. The second shows that multiple quoted tokens are all de-quoted. The last three show that sendmail refuses to dequote any tokens that will form an illegal or ambiguous address when dequoted.

> As an aid to understanding this dequoting process, run the following two-line configuration file in rule-testing mode:

> >     V7
> >     Kdequote dequote

> You can then use the `-bt` `/map` command to try various dequoting possibilities:

> >     > /map dequote "A.B.C"
> >     map_lookup: dequote ("A.B.C") returns A.B.C (0)
> >     > /map dequote "A"."B"."C"
> >     map_lookup: dequote ("A"."B"."C") returns A.B.C (0)
> >     > /map dequote "A B"
> >     map_lookup: dequote ("A B") no match (0)

> Note that beginning with V8.7, specifying the `-s` switch causes the space character to be replaced with another character before dequoting (see Section 33.3.4.10).

> >     V7
> >     Kdequote dequote -s+

> In that case the last example above would become the following:

> >     > /map dequote "A B"
> >     map_lookup: dequote ("A B") returns A+B (0)

> Also note that beginning with V8.8, specifying the `-a` switch causes a suffix of your choice to be appended to a successful match:

> >     V7
> >     Kdequote dequote -a.yes

> In that case the `"A.B.C"` example would become the following:

> >     > /map dequote "A.B.C"
> >     map_lookup: dequote ("A.B.C") returns A.B.C.yes (0)

> In addition to removing quotes, the `dequote` class also tokenizes everything that is returned. It does this because quotes are ordinarily used to mask the separation characters that delimit tokens. For example, consider the `$&` operator. It prevents a macro in a rule from being expanded when the configuration file is read and always returns a single token, no matter how many tokens it really contains. Consider this configuration file:

> >     V7
> >     DXhost.domain
> >     Kdequote dequote
> >     R$*    $: $&X , $(dequote "" $&X $)

> Here, the macro `X` is assigned `host.domain` as its value. The only rule in the file (when sendmail is run in rule-testing mode) prints the expression `$&X` to show that it is a single token, then prints the result of dequoting that same expression. Note that an empty token needs to be dequoted. Putting quotes around `$&X` itself won't work. The output produced by rule-testing mode looks like this:

> >     > 0 foo
> >     rewrite: ruleset  0   input: foo
> >     rewrite: ruleset  0 returns: host.domain , host . domain
> >     >
> >                                  $X        $X dequoted

> No debugging switch is available to watch the actions of the `dequote` class.

### 33.8.5 hash

Berkeley's db form of database

(V8.1 and above)

> The `hash` class uses a hashing algorithm for storing data. This approach to a database is described in A New Hash Package for UNIX, by Margo Seltzer (USENIX Proceedings, Winter 1991). The hash class is available only if sendmail was compiled with `NEWDB` defined and the new Berkeley db library linked in.

> The `hash` class is the default that is used with most of the FEATURES offered by the m4 technique (see Table 33.6 in Section 33.6, "Database Maps and m4"). For example, consider the following:

> >     Kuudomain hash -o /etc/uudomain

> Here, a map named `uudomain` is declared to be of class `hash`. The `-o` says that the file /etc/uudomain is optional.

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with this class and the meaning of each.

### 33.8.6 hesiod

MIT network user authentication services

(V8.7 and above)

> The `hesiod` class of map uses the Hesiod system, a network information system developed as Project Athena. Support of hesiod maps is available only if you declare HESIOD when compiling sendmail. (See Section 18.8.10, HESIOD for a fuller description of the Hesiod system.)

> A `hesiod` map is declared like this:

> >     Kname hesiod HesiodNameType

> The `HesiodNameType` must be one that is known at your site, such as `passwd` or `service`. An unknown `HesiodNameType` will yield this error when sendmail begins to run:

> >     cannot initialize Hesiod map (hesiod error number)

> One example of a lookup might look like this:

> >     Kuid2name hesiod uid
> >     R$+      $: $(uid2name $1 $)

> Here, we declare the map `uid2name` using the Hesiod-type `uid`, which converts uid numbers into login names. If the conversion was successful, we use the login name returned; otherwise, we use the original workspace.

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with this class and the meaning of each.

### 33.8.7 host

Internal table used to store and look up hostnames

(V8.1 and above)

> The `host` class is a special internal database used by sendmail to help it resolve hostnames. It is fully described under the `$[` and `$]` operators in Section 33.4.3.

> The `-d9` debugging switch (see Section 37.5.37, -d9.1) can be used to watch the actions caused by this `host` class.

### 33.8.8 implicit

Search for an aliases database file

(V8.1 and above)

> The `implicit` class refers specifically to aliases(5) files only. It causes sendmail to first try to open a db(3) hash-style alias file, and if that fails or if NEWDB support was not compiled in, it tries to open a ndbm(3)-style database. If that fails, sendmail reads the aliases(5) source file into its internal symbol table.

> Although you can declare and use this class in a configuration file, there is no reason to do so. It is of use only to the internals of sendmail. If `implicit` fails to open an aliases file (probably because of a faulty `AliasFile` (`A`) option; see Section 34.8.1), sendmail will issue the following error if it is running in verbose mode:

> >     WARNING: cannot open alias database bad file name

> If the source aliases file exists but no database form exists, sendmail will read that source file into its internal symbol table using the `stab` class (see Section 33.8.16).

### 33.8.9 ldapx

The Lightweight Directory Access Protocol

(V8.8 and above)

> LDAP stands for Lightweight Directory Access Protocol and provides access to the X.500 directory. The `ldapx` class is used to look up items in that directory service. It is declared like this:

> >     Kname ldapx switches

> Lookups via LDAP are entirely defined by the switches specified. To illustrate, consider the following X.500 entry:

> >     cn=Full Name, o=Organization, c=US
> >     sn=Name
> >     uid=yourname
> >     cn=Full Name
> >     commonname=Full Name
> >     mail=yourname@mailhub.your.domain
> >     objectclass=person
> >     objectclass=deptperson

> To look up a login name in this database and have the official email address for that user returned, you might use a declaration like this:

> >     Kldap ldapx -k"uid=%s" -v"mail" -hldap_host -b"o=Organization, c=US"

> Note that the `-k` switch is in the form of a `ldap_search`(3) filter, where the `key` will replace the `%s` and then the whole expression will be searched for as the `key`. The `-b` is required to specify the base from which to search. Note that a base must be selected such that it ensures that sendmail will always get a unique result.

> The following rule can be used with the above declaration to look up the preferred mail address for a user:

> >     R$* <@ $+ > $*       $: $(ldap $1 $: $1<@$2>$3 $)

> Here we presume that this rule was preceded by a call to rule set 3 to focus on the host part. If the lookup succeeds, the new (unfocused) address is returned from the `mail=` line in the database. Otherwise, the original address is returned.

> A few errors can occur during sendmail's startup that indicate a faulty `K` command:

> >     LDAP map: -h flag is required
> >     LDAP map: -b flag is required
> >     No return attribute in map name

> The first two show that those switches are mandatory. The third prints only to show that the `-v` switch is mandatory if the `-o` switch is absent.

> In addition, each successful lookup can cause a line like the following to be logged via syslog(3):

> >     qid: ldap key => value

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with this class and the meaning of each. Also, Table 33.6 lists several nonstandard switches that are used by this `ldapx` class. Finally, note that the `ldapx` class can be used only if LDAPMAP was defined when sendmail was compiled (see Section 18.8.15, LDAPMAP).

### 33.8.10 netinfo

NeXT Computer's network information services

(V8.7 and above)

> NetInfo is NeXT's implementation of a network-based information service. The `netinfo` class expects a map declaration to be of the following form:

> >     Kname netinfo map

> Other switches may be used with this class, and they have their normal meanings (see Table 33.5 in Section 33.3.4).

> Support of netinfo maps is available only if you declare NETINFO when compiling sendmail (see Section 18.8.27, NETINFO).

### 33.8.11 nis

Sun's Network Information Services (NIS)

(V8.6 and above)

> Sun Microsystems offers a network information service called NIS. It provides the ability to look up various kinds of information in network databases. The `nis` class allows you to access that network information by way of rules in rule sets. You declare an `nis` class map like this:

> >     Kname nis map

> Here, `name` is the identifier that you will later use in rule sets. The `map` is any nis map. Lookups will occur in the default nis domain. If you wish to specify some other domain, you may append an `@` character and the domain name to the `map`:

> >     Kname nis map@domain

> To illustrate, consider the need to look up the name of the central mail server for your department. If such a map were called mailservers, you could use the following configuration file line to look up your domain in that map:

> >     Kmailservers nis -o mailservers
> >     ...
> >     R$* <@ $+ > $*          $: $1<@$2>$3 <$(mailservers $2 $)>
> >     R$* <@ $+ > $* <$+>     $#smtp $@ $4 $: $1 < @ $2 > $3
> >     ...

> Here, we look up the host part of an address (`$2`) in the `mailservers` nis map. The `-o` makes the existence of the map optional. If the host part is found, it is rewritten to be the name of the mail server for that host. In the last rule we forward the original address to that server.

> Without the `-o`, the nonexistence of a map will cause this error to be logged:

> >     Cannot bind to map name in domain domain: reason here

> If nis is not running at all or if sendmail cannot bind to the `domain` specified or the default domain, the following error is logged:

> >     NIS map name specified, but NIS not running

> The `nis` class is available only if sendmail is compiled with NIS defined (see Section 18.8.29, NIS).

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with this class and the meaning of each.

### 33.8.12 nisplus

Sun's newer version of NIS

(V8.7 and above)

> Sun Microsystems's NIS+ is a complete redo of its earlier nis system. The `nisplus` class allows you to look up information using NIS+. The form of that class declaration looks like this:

> >     Kname nisplus map.domain

> Here, the `map` is a NIS+ map name, such as mail_aliases. [7] If the `domain` or `.domain` is missing, the nisplus default domain is used. If the entire `map.domain` is missing, the default becomes mail_aliases.org_dir. The domain org_dir contains all the systemwide administration tables.

> > [7] Note that under NIS+ map names cannot contain a dot, whereas under NIS they could - for example, mail_aliases for NIS+ but mail.aliases for NIS.

> Any lookup failures that can be retried will automatically be retried up to five times, with a sleep(3) of 2 seconds between each try. If the `map.domain` doesn't exist in the local nisplus system, this error is printed when sendmail starts:

> >     Cannot find table map.domain: reason for failure here

> This error is suppressed if the original `K` command declaration included the `-o` switch.

> Two other errors can happen during startup:

> >     map.domain: reason for failure here is not a table
> >     nisplus_map_open(map): can not find key column -k column name here

> You can use the `-k` switch to specify a `key` column to look up. Under nisplus, columns are named, so the `-k` must be followed by a valid name, or the last error above will be printed. You can also use the `-v` switch to specify the `value` column, also a name. If the `-v` is omitted, the last column becomes the default. See Table 33.5 in Section 33.3.4 for a list of the other `K` command switches that can be used with this class and the meaning of each.

### 33.8.13 null

Provide a never found service

(V8.7 and above)

> The `null` class is an internal database that always returns a failed lookup. It is useful for replacing other classes to force failures without errors. Normally, the `null` class is used internally only.

> Consider a tiny configuration file that does not need the use of the aliases facilities. One way to declare aliases would be like this:

> >     O AliasFile=null:

> This tells sendmail to use the `null` class for looking up aliases. Therefore no aliases will ever be found.

> None of the `K` command switches may be used with the `null` class. If you try to use any, they will be silently ignored. No debugging switch is available to watch this `null` class.

### 33.8.14 program

Run an external program to look up the key

(V8.7 and above)

> The `program` class allows you to perform lookups via arbitrary external programs. The form for the declaration of this class looks like this:

> >     Kname program /path arg1 arg2 ...

> The `/path` must be the full pathname to the program. Relative paths will not work, and attempts to use them will log the following error and cause the lookup to fail:

> >     NOQUEUE: SYSERR(bcx): relative name: cannot exec: No such file or directory

> The program is run under the uid and gid of the person who ran sendmail. But if that person is root, the program is instead run as the user and group specified by the `DefaultUser`(`u`) option (see Section 34.8.15, DefaultUser (g)(u)).

> The arguments to the program always have the key to be looked up added as a final argument:

> >     Kname program /path arg1 arg2 ...

> >                                         key added here

> This is the only way that the key can be passed to the program. The key will specifically not be piped to the program's standard input.

> The value (result of the lookup) is read from the program's standard output. Only the first MAXLINE-1 characters are read (where MAXLINE is defined in conf.h, currently as 2048). The read result is processed as an address and placed into the workspace (unless the `-m` switch is used with the `K` command).

> To illustrate, consider the need to look up a user's preferred address in an external relational database:

> >     Kilook program /usr/lib/ingres_lookup -d users.database

> This program has been custom written to accept the key as its final argument. To prevent spurious errors, it exits with a zero value whether the key is found or not. Any system errors cause it to exit with a value selected from those defined in <sysexits.h> (those recognized by sendmail). Error messages are printed to the standard error output, and the found value (if there was one) is printed to the standard output.

> In general, it is better to use one of the database formats known to sendmail than to attempt to look up keys via external programs. The process of fork(2)ing and exec(2)ing the program can become expensive if it is done often, slowing down the handling of mail.

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with this class and the meaning of each.

### 33.8.15 sequence

Search a series of maps

(V8.7 and above)

> The `sequence` class is a more general form of the `implicit` class described for use with alias files. The `sequence` class allows you to declare a single name that will be used to search a series of databases. It is declared like this:

> >     Kname sequence map1 map2 ...

> Here, a `key` will be looked up first in the map named `map1`, and if not found there, it will be looked up in the map named `map2`. The class of each of the listed maps should logically relate but need not be the same. Consider, for example, a rule's LHS that will match if the workspace contains either a user's login name or the name of a host, with the hostname taking precedence:

> >     Khosts host  -a+ /etc/hosts
> >     Kpasswd user -a- /etc/passwd
> >     Kboth sequence hosts passwd

> >     R$-     $: $(both $1 $)

> Here, we say that the map named `both` is of type `sequence`. Any single token in the LHS will be looked up first in the map named `hosts`, and if it is found there the hostname will be returned with a `+` appended. If it is not found in the `hosts` map, it will be next looked up in the `passwd` map. If it is found there, the original workspace will be returned with a `-` appended. If the workspace is not found in either map, the lookup fails and the workspace remains unchanged.

> If any map in the series of maps declared with the `K` command does not exist:

> >     Kboth sequence hosts passwd badname

> the following error is printed, and that map is ignored:

> >     Sequence map both: unknown member map badname

> If the number of maps that are sequenced exceeds the maximum allowed (MAXMAPSTACK in conf.h, currently 12), the following error is printed, and the overflow of maps is ignored:

> >     Sequence map name: too many member maps (max max)

> None of the `K` command switch may be used with the `sequence` class. If you try to use any, they will be wrongly interpreted as map names.

### 33.8.16 stab

Internally load aliases into the symbol table

(V8.6 and above)

> The `stab` class is used internally by sendmail to load the raw aliases(5) file into its internal symbol table. [8] This is a fallback position that is taken if no database form of aliasing is found.

> > [8] As such it is somewhat misnamed. One might reasonably expect a class named `stab` to provide access to the symbol table, but alas, it is not so.

> The `stab` class should never be used in configuration files.

### 33.8.17 switch

Built sequences based on service switch

(V8.7 and above)

> The `switch` class is used internally by sendmail to create `sequence` classes of maps based on external service-switch files. Recall that the lines inside a service-switch file look like this:

> >     service  how how

> as, for example:

> >     aliases   files nis

> This line tells sendmail to search for its aliases first in files then in NIS.

> To illustrate the `switch` class, consider the need to look up aliases inside rule sets in the same way that sendmail looks up its own aliases. To do this, you would declare a `switch` map, as, for example:

> >     Kali switch aliases

> This causes sendmail to search for the `service` named `aliases` in the service-switch file. In this example it finds such a line, so for each `how` that follows the `aliases` in that line, sendmail creates a new map with the name `ali` followed by a dot and the `how`: [9]

> > [9] Your `switch` map declaration references the new maps named `ali.files` and `ali.nis`. These must be declared before the `switch` map is declared. Note that `switch` map declarations always reference other map names!

> >     aliases   files    becomes    ali.files
> >     aliases   nis      becomes    ali.nis

> These named maps are then sequenced for you. Recall that `sequence` maps are declared like this:

> >     Kname sequence map1 map2,...

> The `name` given to the sequence is `ali`. In our example the following sequence is automatically created for you from your original `switch` declaration:

> >     Kali sequence ali.files ali.nis

> In rule sets, when you look up aliases with the `ali` map:

> >     R...        $( ali $1 $)

> >               the sequence named ali

> you will use the `sequence` named `ali` that was automatically built for you from a combination of your original `switch` definition and your service-switch file's `aliases` line. That is, you declare a `switch`, but you use a `sequence`.

### 33.8.18 text

Look up in flat text files

(V8.7 and above)

> The `text` class allows you to look up keys in flat text files. This technique is vastly less efficient than looking up keys in real databases, but it can serve as a way to test rules before implementing them in database form.

> For the `text` map, columns for the key and value are both measured as an index. That is, the first column is number 0. To illustrate, consider the following miniconfiguration file that can be used to check spelling:

> >     Kspell text /usr/dict/words
> >     Spell
> >     R$-      $: $( spell $1 $: not in dictionary $)

> The /usr/dict/words file contains only a single column of words. The above rule shows that the key is (by default) the first column (index 0). And the value is (by default) also the first column (index 0).

> For more sophisticated applications you can specify the key's column (with the `-k` switch) the value's column (with the `-v` switch) and the column delimiter (with the `-z` switch). To illustrate, consider the need to look up a uid in the /etc/passwd file and to return the login name of the user to whom it belongs:

> >     Kgetuid text -k2 -v0 -z: /etc/passwd
> >     R$-      $: $( getuid $1 $)

> The lines of a password file look like this:

> >     ftp:*:1092:255:File Transfer Protocol Program:/u/ftp:/bin/sh

> The third column (where the columns are separated by colons) is the uid field. The first is the login name. Note that the `-k` and `-v` switches show these fields as indexes, where the first is 0 and the third is 2.

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with this class and the meaning of each. No debugging switch is available to watch this `text` class.

### 33.8.19 userdb

Look up in the User Database

(V8.7 and above)

> The `userdb` class allows you to look things up in the User Database (see Section 33.5, "The User Database" for a full description of the User Database). The `userdb` class is declared with the `K` command like this:

> >     Kname userdb switches keyword      V8.7 and above

> Here, the `keyword` is the name of the field to search and is either `maildrop` or `mailname` (see Section 33.5). There is no need to list any files or servers with this command. Those should already have been declared with the `UserDatabaseSpec` (`U`) option (see Section 34.8.75).

> One possible use for a `userdb` map might be to check for a local account in the `check_rcpt` rule set (see \#sRULESETS_check_rcpt). In this example, all valid incoming recipient addresses are listed with the User Database:

> >     Kislocal userdb maildrop
> >     Scheck_rcpt
> >     R$*                     $: $>3 $1               focus on host
> >     R$* <@ $+ > $*          $: $1                   discard host
> >     R$+                     $: $(islocal $1 $: nope $)
> >     Rnope                   $#error $@ 5.1.3 $: "Recipient is not local"

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with this class and the meaning of each. The `-d28` debugging switch (see Section 37.5.97, -d28.1) can be used to watch this `userdb` class in action.

### 33.8.20 user

Look up local passwd information

(V8.7 and above)

> The `user` class is used to look up passwd(5) information using getpwent(3). A password entry typically looks like this:

> >     ftp:*:1092:255:File Transfer Protocol Program:/u/ftp:/bin/sh

> Here, there are seven fields, each separated from the others by colon characters. The key is always compared to the first field. The value returned is (by default) the first field unless you specify another field with a `-v` switch:

> >     Kname user -vfield

> Here, field can be either a number 1 through 7 or one of the names `name`, `passwd`, `uid`, `gid`, `gecos`, `dir`, or `shell`, which correspond to the numbers. For example, to look up usernames and get the full name (gecos) field returned, you could use something like this:

> >     Kgetgecos user -vgecos
> >     ...
> >     R$-        $: $( getgecos $1 $)

> Note that this returns the full gecos field in its rawest form. It is not cleaned up to provide a reliable full name, as is the `$x` macro (see Section 31.10.42, $x).

> One possible application for the `user` class is in conjunction with the `check_rcpt` rule set (see \#sRULESETS_check_rcpt). In the following we check to see whether a recipient is a local user and reject the mail if that is not so:

> >     Kislocal user
> >     Scheck_rcpt
> >     R$*                     $: $>3 $1               focus on host
> >     R$* <@ $+ > $*          $: $1                   discard host
> >     R$-                     $: $(islocal $1 $: nope $)
> >     Rnope                   $#error $@ 5.1.3 $: "Recipient is not local"

> Here, we focus on the host part with rule set 3, then discard all but the user part in the second rule. The third rule performs the lookup. If the user is found, that username is returned unchanged. If, on the other hand, the user is not found, the token `nope` is returned. The last rule rejects any SMTP RCPT command that contains a nonlocal user part.

> See Table 33.5 in Section 33.3.4 for a list of the `K` command switches that can be used with this class and the meaning of each.

33.7 Pitfalls |  | 34. Options